const express = require('express');
const app = express();
app.listen(9000, () => {
  console.log('服务器9000启动成功');
});

// 同步代码错误：同步代码错误无需进行额外的工作，错误中间件会自动捕获并处理
app.get('/middleware_error_sync', (req, res) => {
  console.log('客户端发送GET请求');
  
  throw new Error('同步代码错误');
  
  console.log('程序继续向下执行'); // 此处不会被打印，表示程序不会在错误后继续向下执行
});

// 异步代码错误
// 1.异步代码错误需要将错误对象作为next参数传递，若未传递则错误中间件捕获不到
app.get('/middleware_error_async', (req, res, next) => {
  console.log('客户端发送GET请求');
  
  setTimeout(() => {
    try {
      throw new Error('异步代码错误');
      
      console.log('程序继续向下执行'); // 此处不会被打印，表示程序不会在错误后继续向下执行
    } catch (err) {
      next(err);
    }
  }, 100);
});
// 2.Promise中发生的错误被Promise的catch捕获，catch回调函数可直接设为next
app.get('/middleware_error_async_promise', (req, res, next) => {
  console.log('客户端发送GET请求');
  
  new Promise((resolve, reject) => {
    throw new Error('异步代码错误Promise');
    
    console.log('程序继续向下执行'); // 此处不会被打印，表示程序不会在错误后继续向下执行
  }).catch(next);
});

// 若发生错误后不存在错误中间件则错误将在控制台直接抛出
app.use((error, req, res, next) => {
  console.log('错误中间件捕获：', error.message);
  next('默认错误信息'); // 此处next将调用Express内置默认错误处理程序，内置默认错误处理程序结束请求并将错误响应到客户端
});

// 内置默认错误处理程序
app.get('/middleware_error_default', (req, res, next) => {
  console.log('客户端发送GET请求');
  
  try {
    throw new Error('内置默认错误处理程序');
    
    console.log('程序继续向下执行'); // 此处不会被打印，表示程序不会在错误后继续向下执行
  } catch (err) {
    next('默认错误信息');
  }
});

// 访问路径 http://localhost:9000/middleware_error_sync 输出结果：客户端发送GET请求 错误中间件捕获：同步代码错误 默认错误信息
// 访问路径 http://localhost:9000/middleware_error_async 输出结果：客户端发送GET请求 错误中间件捕获：异步代码错误 默认错误信息
// 访问路径 http://localhost:9000/middleware_error_async_promise 输出结果：客户端发送GET请求 错误中间件捕获：异步代码错误Promise 默认错误信息
// 访问路径 http://localhost:9000/middleware_error_default 输出结果：客户端发送GET请求 默认错误信息